home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / THINKC / 5 / MACVOGL- / CURVES.C < prev    next >
C/C++ Source or Header  |  1992-07-19  |  5KB  |  286 lines

  1. #include "vogl.h"
  2.  
  3. static    int    nsegs = 15;
  4. static    Matrix    e;
  5.  
  6. void     drcurve();
  7.  
  8. /*
  9.  * curvebasis
  10.  *
  11.  *      sets the basis type of curves.
  12.  *
  13.  */
  14. void
  15. curvebasis(id)
  16.     short   id;
  17. {
  18.     if(!vdevice.initialised)
  19.         verror("curvebasis: vogl not initialised");
  20.  
  21.     copymatrix(vdevice.tbasis, vdevice.bases[id]);
  22. }
  23.                            
  24. /*
  25.  * curveprecision
  26.  *
  27.  *    sets the number of line segments that make up a curve segment.
  28.  *
  29.  */
  30. void
  31. curveprecision(nsegments)
  32.     short        nsegments;
  33. {
  34.     double    n2, n3;
  35.  
  36.     if (nsegments > 0)
  37.         nsegs = nsegments;
  38.     else
  39.         verror("curveprecision: number of segments <= 0");
  40.  
  41.     /*
  42.      * Set up the difference matrix.
  43.      */
  44.     identmatrix(e);
  45.     n2 = (double)(nsegs * nsegs);
  46.     n3 = (double)(nsegs * n2);
  47.  
  48.     e[0][0] = e[2][2] = e[3][3] = 0.0;
  49.     e[1][0] = 1.0 / n3;
  50.     e[1][1] = 1.0 / n2;
  51.     e[2][0] = e[3][0] = 6.0 / n3;
  52.     e[2][1] = 2.0 / n2;
  53.     e[1][2] = 1.0 / (double)nsegs;
  54.     e[0][3] = 1.0;
  55. }
  56.  
  57. /*
  58.  * rcrv
  59.  *
  60.  *    draws a rational curve
  61.  *
  62.  */
  63. void
  64. rcrv(geom)
  65.     Coord    geom[4][4];
  66. {
  67.     Matrix    d, tmp;
  68.     double    *m, xlast, ylast, zlast;
  69.     Token    *tok;
  70.     int    i;
  71.     
  72.     if (!vdevice.initialised)
  73.         verror("rcrv: vogl not initialised");
  74.  
  75.  
  76.     mult4x4(d, vdevice.tbasis, geom);
  77.  
  78.     /*
  79.      * Find the last point on the curve....
  80.      */
  81.     xlast = d[0][0] + d[1][0] + d[2][0] + d[3][0];
  82.     ylast = d[0][1] + d[1][1] + d[2][1] + d[3][1];
  83.     zlast = d[0][2] + d[1][2] + d[2][2] + d[3][2];
  84.  
  85.     /*
  86.      * Mult. by the precision matrix....
  87.      */
  88.     mult4x4(tmp, e, d);
  89.  
  90.     if (vdevice.inobject) {
  91.         tok = newtokens(21);
  92.  
  93.         tok[0].i = RCURVE;
  94.         (++tok)->i = nsegs;
  95.         (++tok)->f = xlast;
  96.         (++tok)->f = ylast;
  97.         (++tok)->f = zlast;
  98.         m = (double *)tmp;
  99.         for (i = 0; i < 16; i++)
  100.             (++tok)->f = *m++;
  101.  
  102.         return;
  103.     }
  104.  
  105.     /*
  106.      * Multiply by the current transformation matrix.
  107.      */
  108.     mult4x4(d, tmp, vdevice.transmat->m);
  109.  
  110.     /*
  111.      * Draw the curve.....
  112.      */
  113.     drcurve(nsegs, d);
  114.     /*
  115.      * Set the current world position to the last point (This
  116.      * is the untransformed one)
  117.      */
  118.     vdevice.cpW[V_X] = xlast;
  119.     vdevice.cpW[V_Y] = ylast;
  120.     vdevice.cpW[V_Z] = zlast;
  121. }
  122.  
  123. /*
  124.  * crv
  125.  *
  126.  *    draws a curve
  127.  *
  128.  */
  129. void
  130. crv(geom)
  131.     Coord    geom[4][3];
  132. {
  133.     Matrix    tmp;
  134.     int    i, j;
  135.  
  136.     if (!vdevice.initialised)
  137.         verror("crv: vogl not initialised");
  138.  
  139.     /*
  140.      * Fill in the w column for rcurve
  141.      */
  142.     for (i = 0; i < 4; i++) {
  143.         tmp[i][3] = 1.0;
  144.         for (j = 0; j < 3; j++) 
  145.             tmp[i][j] = geom[i][j];
  146.     }
  147.  
  148.     rcrv(tmp);
  149. }
  150.  
  151. /*
  152.  *  drcurve
  153.  *
  154.  *    Iterate a forward difference matrix to draw a curve.
  155.  *    Also bypasses the normal multiplication by the current
  156.  *      transformation matrix (ie. goes straight to clip).
  157.  */
  158. void
  159. drcurve(n, r)
  160.     int    n;
  161.     Matrix    r;
  162. {
  163.     int    it, vx, vy;
  164.  
  165.     vdevice.cpVvalid = 0;        /* we start loop with a "move" */
  166.     if (vdevice.clipoff) {
  167.         vdevice.cpVx = WtoVx(r[0]);        
  168.         vdevice.cpVy = WtoVy(r[0]);        
  169.     }
  170.  
  171.     for (it = 0; it < n; it++) {
  172.         vdevice.cpWtrans[V_X] = r[0][V_X];
  173.         vdevice.cpWtrans[V_Y] = r[0][V_Y];
  174.         vdevice.cpWtrans[V_Z] = r[0][V_Z];
  175.         vdevice.cpWtrans[V_W] = r[0][V_W];
  176.  
  177.         /* These loops now unwound ....
  178.          * for (i = 0; i < 4; i++)
  179.          *    for (j = 0; j < 3; j++)
  180.          *        r[j][i] += r[j+1][i];
  181.          */
  182.  
  183.         r[0][0] += r[1][0];
  184.         r[1][0] += r[2][0];
  185.         r[2][0] += r[3][0];
  186.  
  187.         r[0][1] += r[1][1];
  188.         r[1][1] += r[2][1];
  189.         r[2][1] += r[3][1];
  190.  
  191.         r[0][2] += r[1][2];
  192.         r[1][2] += r[2][2];
  193.         r[2][2] += r[3][2];
  194.  
  195.         r[0][3] += r[1][3];
  196.         r[1][3] += r[2][3];
  197.         r[2][3] += r[3][3];
  198.  
  199.         if (vdevice.clipoff) {    
  200.             vx = WtoVx(r[0]);        /* just draw it */
  201.             vy = WtoVy(r[0]);
  202.          
  203.             (*vdevice.dev.Vdraw)(vx, vy);
  204.  
  205.             vdevice.cpVx = vx;
  206.             vdevice.cpVy = vy;
  207.  
  208.             vdevice.cpVvalid = 0;
  209.         } else {
  210.             if (vdevice.cpVvalid)
  211.                 quickclip(vdevice.cpWtrans, r[0]);
  212.             else
  213.                 clip(vdevice.cpWtrans, r[0]);
  214.         }
  215.     }
  216.  
  217.     vdevice.cpWtrans[V_X] = r[0][V_X];
  218.     vdevice.cpWtrans[V_Y] = r[0][V_Y];
  219.     vdevice.cpWtrans[V_Z] = r[0][V_Z];
  220.     vdevice.cpWtrans[V_W] = r[0][V_W];
  221.  
  222.     /*
  223.      * must set current world position here - clip or quickclip will have
  224.      * set valid to the approriate value.
  225.      */
  226. }
  227.  
  228. /*
  229.  * crvn
  230.  *
  231.  *    draws a series of curve segments.
  232.  *
  233.  */
  234. void
  235. crvn(n, geom)
  236.     long    n;
  237.     Coord    geom[][3];
  238. {
  239.     int    i;
  240.  
  241.     if (!vdevice.initialised)
  242.         verror("crvn: vogl not initialised");
  243.  
  244.     if (n < 4)
  245.         verror("crvn: not enough points in geometry matrix");
  246.  
  247.     for (i = 0; i <= n - 4; i++)
  248.         crv(&geom[i][0]);
  249. }
  250.  
  251. /*
  252.  * rcrvn
  253.  *
  254.  *    draws a series of rational curve segments.
  255.  *
  256.  */
  257. void
  258. rcrvn(n, geom)
  259.     long    n;
  260.     Coord    geom[][4];
  261. {
  262.     int    i;
  263.  
  264.     if (!vdevice.initialised)
  265.         verror("rcrvn: vogl not initialised");
  266.  
  267.     if (n < 4)
  268.         verror("rcrvn: not enough points in geometry matrix");
  269.  
  270.     for (i = 0; i <= n - 4; i++)
  271.         rcrv(&geom[i][0]);
  272. }
  273.  
  274. /*
  275.  * curveit
  276.  *
  277.  *    Iterates the top matrix on the stack as a forward difference
  278.  *    matrix, drawing as it goes along.
  279.  */
  280. void
  281. curveit(n)
  282.     short    n;
  283. {
  284.     drcurve((int)n, vdevice.transmat->m);
  285. }
  286.